/* TO DO :
 * Ujednolicenie metod, niektore zwracja wartosci logiczne ine nie (poprawnosc dzialania)
 * Obluga wyjatkow ... bledy ... 
 * Czy jest potrzebny track controls ?
 * CO z state helperem ? 
 * Tablice dla procesorw ? 
 * Ustwaianie formatow wrzucic do metody, mozliwosc zmiany
 * 
 * 
 * 
 * 
 */


import java.io.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Vector;

import javax.media.*;
import javax.media.protocol.*;
import javax.media.format.*;
import javax.media.control.TrackControl;
import javax.media.rtp.*;
import javax.media.rtp.rtcp.SourceDescription;
import javax.swing.JOptionPane;


public class AV_Transmiting{
   private MediaLocator ml_a;
   private static MediaLocator ml_v;
   static Processor procesor_a = null;
   static Processor procesor_v = null;
   private static StateHelper sh_v = null;
   private static StateHelper sh_a = null;
   private TrackControl track_v[] = null;
   private TrackControl track_a[] = null;
   private TrackControl all_Tracks[] = new TrackControl[2];
   private DataSource ds_v = null;
   private DataSource ds_a = null;
   private AudioFormat format_a = new AudioFormat(AudioFormat.DVI_RTP);
   private DataSource ds_v_clone = null;
   private DataSource ds_a_clone = null;
   static SendStream sendStream;
   static SendStream sendStream2;
   public static RTPManager mgr_a =null;
   public static RTPManager mgr_v =null;
   int port_VZ=4000; // zajmowany port lokalny dla strumienia VIdeo
   int port_AZ=4226;

   //metoda ustwiajaca urzdzenia przychwytywania (lok_a - audio, lok_v - video)
   public AV_Transmiting(String lok_a, String lok_v){
	   ml_a = new MediaLocator(lok_a);
	   ml_v = new MediaLocator(lok_v);

   }


   //tworzymy procesor video jesli sie powiedzie zwracamy true ...
   public boolean createProcessor_V(){
	   
	
	  boolean ok = true;
	  
	  try {
		procesor_v = Manager.createProcessor(ml_v);
		sh_v = new StateHelper(procesor_v);
	  }
	  catch (IOException e) {
		
		  return ok; 
	  } catch (NoProcessorException e){
		 
		  ok= false;
		 return ok;
	  }
	  
	  return ok;
   }
   
   //tworzymy procesor audio ... analogicznie do p.video
   public boolean createProcessor_A(){
	   

	   boolean ok = true;
		  
		  try {
			procesor_a = Manager.createProcessor(ml_a);
			sh_a = new StateHelper(procesor_a);
		  }
		  catch (IOException e) {
			  ok = false;
			  return ok;
		  } catch (NoProcessorException e){
			  ok= false;
			  return ok;
			  
		  }
		  
		  return ok;
   }
   
   public void setConfigure(){
	   setState(sh_v,"configure");
		setState(sh_a, "configure");
   }

   //Metoda sluzaca do ustwienia procesora w odpowieni stan (configure lub realize)
   //Korzysta z klasy StateHelper z tutoriala
   public boolean setState(StateHelper setSTATE, String state){
	   boolean ok = false;
	   int STATE = 0;
	   if (state == "configure") STATE=0;
	   if (state == "realize") STATE=1;
	   switch (STATE){
	   case 0 : setSTATE.configure(12000); break; //czekamy na stan 10000 m. sekund
	   case 1 : setSTATE.realize(12000); break;
	   }
	   
	   return ok;
   }
   
   
   
   
   ////Ustawiamy format strumieni wyjsciowych dla obu procesorow 
   public void setCD_v(){
	   procesor_v.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW_RTP));
   }
   
   public void setCD_a(){
	   procesor_a.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW_RTP));
   }
  //pobieramy sciezki z poszczegolnych procesorow i kopiujemy do jednej tablicy DO ZMIANY ...
   public void getTC(){
	  track_v= procesor_v.getTrackControls();
	  track_a= procesor_a.getTrackControls();
	  System.out.println("Iloosc sciezek   video : " + track_v.length);
	  System.out.println("Ilosc sciezek   audio : " + track_a.length);
	  
	 all_Tracks[0] = track_v[0];
	 all_Tracks[1] = track_a[0];
	  
	 
   }
   
  
   //poszczgolnym sciezkom ustawiamy wczesnje zdefiniowane formaty 
   public void setOT(String format_v){
     VideoFormat format;
     System.out.println("Jestem w setOT" + format_v);
     System.out.println(format_v);

     if (format_v.equals( "VideoFormat.JPEG_RTP")) {
       format = new VideoFormat(VideoFormat.JPEG_RTP);
    all_Tracks[0].setFormat(format);
     }
     
     if (format_v.equals( "VideoFormat.H263_RTP")) {
        format = new VideoFormat(VideoFormat.H263_RTP);
      all_Tracks[0].setFormat(format);
       } 
     
         
    all_Tracks[1].setFormat(format_a);
    }

   
   public void setRealize() {
	   setState(sh_v,"realize");
	   setState(sh_a,"realize");
   }
		
		//Pobieramy dataSourc`e z obu procesorw ...
   public void getDATAS(){
			 try {
				 ds_v= procesor_v.getDataOutput();
			 }catch (NotRealizedError e){
				 System.exit(-1);
			 }
			 
			 try {
				 ds_a= procesor_a.getDataOutput();
			 }catch (NotRealizedError e){
				 System.exit(-1);
			 }
			 
		 }
   
   public void AddTargets(String [] targets, String type) throws InvalidSessionAddressException, IOException {

	String IP;
	String porty;
	String port_a;
	String port_v;
	 int port_A;
	 int port_V;
	 
	 
	   
	 for (int i=0; i<=targets.length-1; i++)
	   {  
		  IP=(targets[i].substring(targets[i].indexOf("*")+1,targets[i].indexOf("/"))); 
		
		  porty=(targets[i].substring(targets[i].indexOf("/")+1,targets[i].length()));
		  port_v=(porty.substring(0,porty.indexOf("/")));
		  port_a=(porty.substring(porty.indexOf("/")+1,porty.length()));
		  
		  port_V = Integer.valueOf(port_v).intValue();
		  port_A = Integer.valueOf(port_a).intValue();
		  int port = 0;
	
		  if(type=="video") port=port_V;
		  if (type=="audio") port=port_A;
		  
		  InetAddress ipAddress = null;
	
			ipAddress = InetAddress.getByName(IP);
	
		 SessionAddress  remoteAddress =new SessionAddress( ipAddress, port);
		  
		   if (type=="video"){
		  	mgr_v.addTarget(remoteAddress);}
		   else{
			mgr_a.addTarget(remoteAddress);}
		


	
		
		  System.out.println("IP: " + IP);
		  System.out.println("Port video: " + port_V);
		  System.out.println("Port audio: " + port_A);
	   }
	   
	  
   }
		 // tworzymy RTPManager dla Video - nowa klasa JMF 2.1.1.e , w starym jmf SessionManager ....
		 public void createSMGR_V(String [] adress) throws InvalidSessionAddressException, IOException, UnsupportedFormatException{
		
			 System.out.println("$$$$$$$$$$$$$$$$$$ MGR NR :" + Komunikator.tr_counter);
			System.out.println("port video zajmowany" + port_VZ);
			
		//rtp_MGR = RTPManager.newInstance();
		
		mgr_v= RTPManager.newInstance();
	
		
		 SessionAddress localAddress = new SessionAddress(InetAddress.getLocalHost(),
					port_VZ);

		 

		mgr_v.initialize(localAddress);
		 	
		 	AddTargets(adress,"video");
		
		 	sendStream = mgr_v.createSendStream( ds_v, 0);
		 
		 	
		 	Vector v = sendStream.getParticipant().getSourceDescription();
		 	System.out.println("Source Description" + v.size());
		 	((SourceDescription) v.elementAt(0)).setDescription("audio@tr.rtp");
		 	
		 	sendStream.start();
			//Nie jest to start transmisjii
			  
		 } 	

		 
		 // RTP Manager Audio - analogicznie do Video
		 public void createSMGR_A(String [] adress) throws InvalidSessionAddressException, IOException, UnsupportedFormatException{
				System.out.println("Port audio lokalny" + port_AZ);
				System.out.println("$$$$$$$$$$$$$$$$$$ MGR NR :" + Komunikator.tr_counter);

				mgr_a=RTPManager.newInstance();
			
				 SessionAddress localAddress = new SessionAddress(InetAddress.getLocalHost(),
							port_AZ);

				 	mgr_a.initialize(localAddress);
				
				 AddTargets(adress,"audio");

				 sendStream2 = mgr_a.createSendStream( ds_a, 0);
					
				 sendStream2.start();
			
				 
		 }
		 
		 //Tworzy kolejne transmisje - tylko gdy juz jakas istnieje 
			public void createNextTransmision (String [] adress) throws InvalidSessionAddressException, IOException, UnsupportedFormatException{
			System.out.println("------------------");
				System.out.println(Komunikator.tr_counter);
			
			
			AddTargets(adress,"video");
			AddTargets(adress,"audio");	
		
			}
		 
		 
	 
		 // Dopiero uruchominie procesorow powoduje start transmisji 
		 public void startTRANSMISION(){
			 procesor_v.start();
			 procesor_a.start();
			 
			 
		 }
		 
		 public static void stopTRANSMISION(){
			 
			 if (mgr_a!=null || mgr_v!=null){
			 
			 procesor_a.stop();
			 procesor_a.close();
			 procesor_a=null;
			 
			 mgr_a.removeTargets("Usuwam odbiorcow");
			 mgr_a.dispose();
			 
			 procesor_v.stop();
			 procesor_v.close();
			 procesor_v=null;
			 
			 mgr_v.removeTargets("Usuwam odbiorcow");
			 mgr_v.dispose();
			 
			 mgr_a=null;
			 mgr_v=null;
			 
			 Komunikator.tr_counter=0;
			 }
			 else System.out.println("BRAK WYCHODZACYCH POLACZEN");
		 }

}
		
		//Odowlujemy sie do urzadzen przechwytujacych, korzystamy z Java Sound i Video for Vindows (VFW)
 
		/*
		 *Przykla uzycia klasy :
		 *
		AV_Transmiting fff = new AV_Transmiting("javasound://44100","vfw://0");
		System.out.println(fff.creatPrcoessor_V());
		System.out.println(fff.createProcessor_A());
		fff.setConfigure();
		fff.setCD_v();
		fff.setCD_a();
		fff.getTC();
		fff.setOT(); // Zmienic nazwe metody ...  
		fff.setRealize();
		fff.getDATAS();
		fff.createSMGR_V(tabliczka_);
		fff.createSMGR_A(tabliczka_);
		fff.startTRANSMISION();
		
	
	
*/


